﻿using BCCommon;
using BCCommon.Enums;
using BCData.MySql.BusinessFlowInstance;
using BCData.MySql.BusinessFlowStepInstance;
using BCData.OA.BusinessFlowModel.BusinessFlowModel;
using BCData.OA.BusinessFlowModel.BusinessFlowStepModel;
using BCData.Sim.Company.Company;
using BCDto.MySql.BusinessFlowInstance;
using BCDto.MySql.BusinessFlowStepInstance;
using BCEntity.MySql.BusinessFlowInstance;
using BCEntity.MySql.BusinessFlowStepInstance;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BCService.OA.BusinessFlowInstance
{
    public class BusinessFlowInstanceService : IBusinessFlowInstanceService
    {
        private readonly IBusinessFlowInstanceData businessFlowInstanceData;
        private readonly IBusinessFlowStepInstanceData businessFlowStepInstanceData;
        private readonly IBusinessFlowModelData businessFlowModelData;
        private readonly IBusinessFlowStepModelData businessFlowStepModelData;
        private readonly ICompanyData companyData;

        public BusinessFlowInstanceService(IBusinessFlowInstanceData businessFlowInstanceData,
            IBusinessFlowStepInstanceData businessFlowStepInstanceData,
            IBusinessFlowModelData businessFlowModelData,
            IBusinessFlowStepModelData businessFlowStepModelData,
            ICompanyData companyData)
        {
            this.businessFlowInstanceData = businessFlowInstanceData;
            this.businessFlowStepInstanceData = businessFlowStepInstanceData;
            this.businessFlowModelData = businessFlowModelData;
            this.businessFlowStepModelData = businessFlowStepModelData;
            this.companyData = companyData;
        }

        public bool Exists(long businessFlowInstanceId)
        {
            return this.businessFlowInstanceData.Exists(businessFlowInstanceId).GetAwaiter().GetResult();
        }

        public BusinessFlowInstanceDto Add(BusinessFlowInstanceRequestDto requestDto)
        {
            if (!this.businessFlowModelData.Exists(requestDto.BusinessFlowModelId).GetAwaiter().GetResult())
            {
                throw new ArgumentException("此业务流模型不存在");
            }
            if (!this.companyData.CheckCompanyExists(requestDto.CompanyId).GetAwaiter().GetResult())
            {
                throw new ArgumentException("此公司不存在");
            }
            var businessFlowModelEntity = this.businessFlowModelData.GetEntity(requestDto.BusinessFlowModelId).GetAwaiter().GetResult();
            var companyEntity = this.companyData.GetEntity(requestDto.CompanyId).GetAwaiter().GetResult();

            var entity = requestDto.As<BusinessFlowInstanceEntity>();
            entity.BusinessFlowModelName = businessFlowModelEntity.BusinessFlowModelName;
            entity.TotalStep = businessFlowModelEntity.TotalStep;
            entity.CompanyName = companyEntity.CompanyName;
            entity.CurrentlyStep = 1;
            var result = this.businessFlowInstanceData.Add(entity).GetAwaiter().GetResult().As<BusinessFlowInstanceDto>();
            if (result == null)
            {
                throw new ArgumentException("添加业务流实例失败");
            }

            var stepEntities = this.businessFlowStepModelData.GetList(entity.BusinessFlowModelId).GetAwaiter().GetResult();
            var stepInstanceEntities = stepEntities.As<List<BusinessFlowStepInstanceEntity>>();
            foreach (var item in stepInstanceEntities)
            {
                item.BusinessFlowInstanceId = result.BusinessFlowInstanceId;
                item.BusinessFlowInstanceName = result.BusinessFlowInstanceName;
            }
            if (!this.businessFlowStepInstanceData.Add(stepInstanceEntities).GetAwaiter().GetResult())
            {
                bool deleteResult = false;
                while (!deleteResult)
                {
                    deleteResult = this.businessFlowInstanceData.Delete(result.BusinessFlowInstanceId).GetAwaiter().GetResult();
                }
                throw new ArgumentException("添加业务流步骤实例失败");
            }
            result.Steps = this.businessFlowStepInstanceData.GetList(result.BusinessFlowInstanceId).GetAwaiter().GetResult().As<List<BusinessFlowStepInstanceDto>>();

            return result;
        }

        public BusinessFlowInstanceDto Update(BusinessFlowInstancePutDto putDto)
        {
            if (!this.Exists(putDto.BusinessFlowInstanceId))
            {
                throw new ArgumentException("此记录不存在");
            }
            var entity = putDto.As<BusinessFlowInstanceEntity>();
            return this.businessFlowInstanceData.Update(entity).GetAwaiter().GetResult().As<BusinessFlowInstanceDto>();
        }

        public BusinessFlowInstanceDto GetEntity(long businessFlowInstanceId)
        {
            return this.businessFlowInstanceData.GetEntity(businessFlowInstanceId).GetAwaiter().GetResult().As<BusinessFlowInstanceDto>();
        }

        public IEnumerable<BusinessFlowInstanceDto> GetList(int companyId)
        {
            return this.businessFlowInstanceData.GetList(companyId).GetAwaiter().GetResult().As<IEnumerable<BusinessFlowInstanceDto>>();
        }

        public PageableList<BusinessFlowInstanceDto> Query(long? businessFlowModelId, string businessFlowInstanceName, DateTime? start, DateTime? end, int pageIndex, int pageSize)
        {
            var (list, count) = this.businessFlowInstanceData.Query(businessFlowModelId, businessFlowInstanceName, start, end, pageIndex, pageSize).GetAwaiter().GetResult();

            return new PageableList<BusinessFlowInstanceDto>
            {
                Items = list.As<IEnumerable<BusinessFlowInstanceDto>>(),
                Count = count,
                PageIndex = pageIndex,
                PageSize = pageSize
            };
        }
    }
}